home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
001-100
/
001-025
/
022
/
pemacs
/
search.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-17
|
7KB
|
316 lines
/*
* The functions in this file implement commands that search in the forward
* and backward directions. There are no special characters in the search
* strings. Probably should have a regular expression search, or something
* like that.
*
* REVISION HISTORY:
*
* ? Steve Wilhite, 1-Dec-85
* - massive cleanup on code.
*
* Andy Poggio, 1 Apr 86 - added query replace
*/
#include <stdio.h>
#include "ed.h"
/*
* Query replace. Replace pattern with new one at user's discretion.
* Bound to META-%.
*/
qreplace(f, n)
{
register int s;
short olen, repall;
char newpat[ NPAT];
if ((s = readpattern("Replace old string", 0)) != TRUE)
return (s);
olen = strlen( pat);
if((s = mlreply( "with new string: ", newpat, sizeof newpat)) == ABORT)
return( s);
repall = FALSE;
while( search()) {
if( repall) s = TRUE;
else {
mlwrite("Replace?");
update();
askuser:
switch( (*term.t_getchar)()) {
case '\0177':
case '':
case 'n':
s = FALSE; /* don't replace */
break;
case 'a':
repall = TRUE;
case ' ':
case 'y':
s = TRUE; /* replace */
break;
case '\007':
s = ABORT;
break;
default:
mlwrite(
"y or <SP>: replace; n or <DEL>: don't; a: all; <^G>: abort");
update();
goto askuser;
break;
}
}
if( s == TRUE) {
backdel( TRUE, olen); /* delete old string */
s = linsertstr( newpat); /* and insert the new */
}
if( s == ABORT)
break;
}
mlwrite("");
return( s);
}
/*
* Search forward. Get a search string from the user, and search, beginning at
* ".", for the string. If found, reset the "." to be just after the match
* string, and [perhaps] repaint the display. Bound to "C-S".
*/
forwsearch(f, n)
{
register int s;
if ((s = readpattern("Search", 0)) != TRUE)
return (s);
s = search();
if( ! s) mlwrite("Not found");
return( s);
}
search()
{
register LINE *clp;
register int cbo;
register LINE *tlp;
register int tbo;
register int c;
register char *pp;
clp = curwp->w_dotp;
cbo = curwp->w_doto;
while (clp != curbp->b_linep)
{
if (cbo == llength(clp))
{
clp = lforw(clp);
cbo = 0;
c = '\n';
}
else
c = lgetc(clp, cbo++);
if (eq(c, pat[0]) != FALSE)
{
tlp = clp;
tbo = cbo;
pp = &pat[1];
while (*pp != 0)
{
if (tlp == curbp->b_linep)
goto fail;
if (tbo == llength(tlp))
{
tlp = lforw(tlp);
tbo = 0;
c = '\n';
}
else
c = lgetc(tlp, tbo++);
if (eq(c, *pp++) == FALSE)
goto fail;
}
curwp->w_dotp = tlp;
curwp->w_doto = tbo;
curwp->w_flag |= WFMOVE;
return (TRUE);
}
fail:;
}
return (FALSE);
}
/*
* Reverse search. Get a search string from the user, and search, starting at
* "." and proceeding toward the front of the buffer. If found "." is left
* pointing at the first character of the pattern [the last character that was
j matched]. Bound to "C-R".
*/
backsearch(f, n)
{
register LINE *clp;
register int cbo;
register LINE *tlp;
register int tbo;
register int c;
register char *epp;
register char *pp;
register int s;
if ((s = readpattern("Reverse search", 0)) != TRUE)
return (s);
for (epp = &pat[0]; epp[1] != 0; ++epp)
;
clp = curwp->w_dotp;
cbo = curwp->w_doto;
for (;;)
{
if (cbo == 0)
{
clp = lback(clp);
if (clp == curbp->b_linep)
{
mlwrite("Not found");
return (FALSE);
}
cbo = llength(clp)+1;
}
if (--cbo == llength(clp))
c = '\n';
else
c = lgetc(clp, cbo);
if (eq(c, *epp) != FALSE)
{
tlp = clp;
tbo = cbo;
pp = epp;
while (pp != &pat[0])
{
if (tbo == 0)
{
tlp = lback(tlp);
if (tlp == curbp->b_linep)
goto fail;
tbo = llength(tlp)+1;
}
if (--tbo == llength(tlp))
c = '\n';
else
c = lgetc(tlp, tbo);
if (eq(c, *--pp) == FALSE)
goto fail;
}
curwp->w_dotp = tlp;
curwp->w_doto = tbo;
curwp->w_flag |= WFMOVE;
return (TRUE);
}
fail:;
}
}
/*
* Compare two characters. The "bc" comes from the buffer. It has it's case
* folded out. The "pc" is from the pattern.
*/
eq(bc, pc)
int bc;
int pc;
{
if (bc>='a' && bc<='z')
bc -= 0x20;
if (pc>='a' && pc<='z')
pc -= 0x20;
if (bc == pc)
return (TRUE);
return (FALSE);
}
/*
* Read a pattern. If newpat == 0, do the following.
* Stash it in the external variable "pat". The "pat" is not
* updated if the user types in an empty line. If the user typed an empty line,
* and there is no old pattern, it is an error. Display the old pattern, in the
* style of Jeff Lomicka. There is some do-it-yourself control expansion.
* If netpat != 0, ignore the old pattern.
*/
readpattern(prompt, newpat)
char *prompt, *newpat;
{
register char *cp1;
register char *cp2;
register int c;
register int s;
char tpat[NPAT+20];
cp1 = &tpat[0]; /* Copy prompt */
cp2 = prompt;
while ((c = *cp2++) != '\0')
*cp1++ = c;
if ((newpat == 0) && (pat[0] != '\0')) /* Old pattern */
{
*cp1++ = ' ';
*cp1++ = '[';
cp2 = &pat[0];
while ((c = *cp2++) != 0)
{
if (cp1 < &tpat[NPAT+20-6]) /* "??]: \0" */
{
if (c<0x20 || c==0x7F) {
*cp1++ = '^';
c ^= 0x40;
}
else if (c == '%') /* Map "%" to */
*cp1++ = c; /* "%%". */
*cp1++ = c;
}
}
*cp1++ = ']';
}
*cp1++ = ':'; /* Finish prompt */
*cp1++ = ' ';
*cp1++ = '\0';
s = mlreply(tpat, newpat ? newpat : tpat, NPAT); /* Read pattern */
if (s == TRUE) { /* Specified */
if( newpat == 0) strcpy(pat, tpat);
} else if (s == FALSE && newpat == 0 && pat[0] != 0)/* CR, but old one */
s = TRUE;
return (s);
}